package com.exercise.widgets.recyclerview.selection.viewmodel

import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.exercise.struct.viewmodel.BaseViewModel
import com.exercise.widgets.recyclerview.selection.entity.Contact
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.onCompletion
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.retry
import kotlinx.coroutines.launch
import kotlin.random.Random

class SelectionListViewModel : BaseViewModel() {
    private val TAG = "SelectionListViewModel"

    private val mPhonePrefix =
        arrayOf("135", "138", "139", "155", "156", "158", "166", "182", "186", "188")

    private val _contacts: MutableLiveData<List<Contact>> = MutableLiveData()
    val contacts: LiveData<List<Contact>> get() = _contacts

    fun loadData() {
        viewModelScope.launch {
            loadContacts()
                .onStart {
                    Log.d(TAG, "loadData >>> onStart")
                }
                .catch {
                    Log.d(TAG, "loadData >>> catch")
                    it.printStackTrace()
                }
                .onCompletion {
                    Log.d(TAG, "loadData >>> onCompletion")
                }.collectLatest {
                    _contacts.value = it
                }
        }
    }

    private fun loadContacts(): Flow<List<Contact>> {
        return flow {
            val contacts = generateContacts()
            emit(contacts)
        }.retry(1)
            .flowOn(Dispatchers.IO)
            .catch { it.printStackTrace() }
    }

    private suspend fun generateContacts(): List<Contact> {
        val prefixRandom = Random(System.currentTimeMillis())
        val phonePrefix = mPhonePrefix[prefixRandom.nextInt(mPhonePrefix.size)]

        val telephone = (0 until 8).fold("$phonePrefix") { acc, _ ->
            "$acc${Random.nextInt(10)}"
        }
        val contacts = (0..50).map {
            delay(50)
            Contact(it.toLong(), "Contact:$it", telephone)
        }
        return contacts
    }

}